﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="Linker.cs" company="">
//   
// </copyright>
// <summary>
//   Defines the Linker type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using WebPart=System.Web.UI.WebControls.WebParts.WebPart;

namespace RSSLinker.SPRSSLinker
{
	/// <summary>
	/// </summary>
	[Guid("cec21082-3e25-427a-bf8e-8f3247b42385")]
	public class Linker : WebPart
	{
		#region Private Fields

		/// <summary>
		/// Array of the 
		/// </summary>
		private readonly ArrayList listsToIncludeArray = new ArrayList();

		/// <summary>
		/// </summary>
		private readonly ArrayList listsToJumpArray = new ArrayList();

		/// <summary>
		/// </summary>
		private string listsToInclude = string.Empty;

		/// <summary>
		/// </summary>
		private string listsToJump = string.Empty;

		/// <summary>
		/// </summary>
		private bool withSubsites;

		private bool openInOtherWindow;

		#endregion

		#region Public Properties

		/// <summary>
		/// Gets or sets a value indicating whether [with subsites].
		/// </summary>
		/// <value><c>true</c> if [with subsites]; otherwise, <c>false</c>.</value>
		[WebBrowsable(true)]
		[Category("Parametri")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Personalizable(PersonalizationScope.Shared)]
		[FriendlyName("Includere i sottositi")]
		[Description("Imposta un valore per la ricerca nei sottositi")]
		public bool WithSubsites
		{
			get { return withSubsites; }

			set { withSubsites = value; }
		}

		/// <summary>
		/// Gets or sets the lists to jump.
		/// </summary>
		/// <value>The lists to jump.</value>
		[WebBrowsable(true)]
		[Category("Parametri")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Personalizable(PersonalizationScope.Shared)]
		[FriendlyName("Elenco delle liste da saltare")]
		[Description("Imposta l'elenco delle liste da saltare separate da ';'")]
		public string ListsToJump
		{
			get { return listsToJump; }

			set { listsToJump = value; }
		}

		/// <summary>
		/// Gets or sets the lists to include.
		/// </summary>
		/// <value>The lists to include.</value>
		[WebBrowsable(true)]
		[Category("Parametri")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Personalizable(PersonalizationScope.Shared)]
		[FriendlyName("Elenco delle liste da includere")]
		[Description("Imposta l'elenco delle liste da includere separate da ';'")]
		public string ListsToInclude
		{
			get { return listsToInclude; }

			set { listsToInclude = value; }
		}

		/// <summary>
		/// Gets or sets a value indicating whether [open in other window].
		/// </summary>
		/// <value><c>true</c> if [open in other window]; otherwise, <c>false</c>.</value>
		[WebBrowsable(true)]
		[Category("Parametri")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Personalizable(PersonalizationScope.Shared)]
		[FriendlyName("Apri in un'altra finestra")]
		[Description("Consente di aprire i link in una nuova finestra")]
		public bool OpenInOtherWindow
		{
			get { return openInOtherWindow; }
			set { openInOtherWindow = value; }
		}

		#endregion

		#region Implemented Methods

		/// <summary>
		/// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
		/// </summary>
		protected override void CreateChildControls()
		{
			base.CreateChildControls();
			try
			{
				BuildWebPart();
			}
			catch (Exception ex)
			{
				SetErrorMessage(ex);
			}
		}

		#endregion

		#region Auxiliary Methods

		/// <summary>
		/// Builds the web part.
		/// </summary>
		private void BuildWebPart()
		{
			SPWeb currentWeb = SPContext.Current.Web;

			GetLists(listsToJumpArray, ListsToJump);
			GetLists(listsToIncludeArray, ListsToInclude);

			Table table = new Table();
			table.Width = new Unit(100, UnitType.Percentage);
			Controls.Add(table);
			AddListsForSite(table, currentWeb);
		}

		/// <summary>
		/// Gets the lists.
		/// </summary>
		/// <param name="array">
		/// The array.
		/// </param>
		/// <param name="value">
		/// The value.
		/// </param>
		private static void GetLists(IList array, string value)
		{
			string[] split = value.Split(';');
			if (split.Length > 0)
				foreach (string s in split)
					array.Add(s.Trim());
		}

		/// <summary>
		/// Adds the lists for site.
		/// </summary>
		/// <param name="table">
		/// The table.
		/// </param>
		/// <param name="currentWeb">
		/// The current web.
		/// </param>
		private void AddListsForSite(Table table, SPWeb currentWeb)
		{
			foreach (SPList list in currentWeb.Lists)
			{
				if ((!listsToJumpArray.Contains(list.Title) && list.AllowRssFeeds) || listsToIncludeArray.Contains(list.Title))
				{
					TableRow row = new TableRow();

					TableCell imageCell = new TableCell();
					row.Cells.Add(imageCell);
					Image image = new Image();
					image.ImageUrl = "/_layouts/images/lstbulet.gif";
					imageCell.Controls.Add(image);

					TableCell linkCell = new TableCell();
					linkCell.Width = new Unit(100, UnitType.Percentage);
					table.Rows.Add(row);
					row.Cells.Add(linkCell);
					
					LinkButton button = new LinkButton();
					button.Text = list.Title;
					string urlToOpen = currentWeb.Url + "/_layouts/listfeed.aspx?List=" + list.ID;

					if (OpenInOtherWindow)
						button.OnClientClick = string.Format("javascript:window.open('{0}')", urlToOpen);
					else button.PostBackUrl = urlToOpen;
					linkCell.Controls.Add(button);
				}
			}

			if (WithSubsites)
				foreach (SPWeb web in currentWeb.Webs)
					AddListsForSite(table, web);
		}

		/// <summary>
		/// Sets the error message.
		/// </summary>
		/// <param name="ex">
		/// The ex.
		/// </param>
		private void SetErrorMessage(Exception ex)
		{
			Controls.Clear();
			Label errorMessage = new Label();
			errorMessage.Text = GetErrorMessage(ex);
			errorMessage.CssClass = "ms-formvalidation";
			Controls.Add(errorMessage);
		}

		/// <summary>
		/// Gets the error message.
		/// </summary>
		/// <param name="ex">
		/// The ex.
		/// </param>
		/// <returns>
		/// </returns>
		private static string GetErrorMessage(Exception ex)
		{
			StringBuilder result = new StringBuilder();
			try
			{
				StackTrace st = new StackTrace(ex, true); 
				result.AppendLine(string.Format(" Stack trace for current level: {0}", st));
				StackFrame[] frames = st.GetFrames();
				if (frames != null)
					foreach (StackFrame sf in frames)
					{
						result.AppendLine(string.Format(" File: {0}", sf.GetFileName()));
						result.AppendLine(string.Format(" Method: {0}", sf.GetMethod().Name));
						result.AppendLine(string.Format(" Line Number: {0}", sf.GetFileLineNumber()));
						result.AppendLine(string.Format(" Column Number: {0}", sf.GetFileColumnNumber()));
					}
			}
			catch
			{
			}

			return result.ToString();
		}

		#endregion
	}
}